#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include "RingQueue.hpp"

struct threaddata
{
    RingQueue<int> *rq;
    std::string name;
};

void *consumer(void *args)
{
    threaddata *td = static_cast<threaddata*>(args);

    while (true)
    {
        sleep(3);
        // 1. 消费任务
        int t = 0;
        td->rq->Pop(&t);

        // 2. 处理任务 -- 处理任务的时候，这个任务，已经被拿到线程的上下文中了,不属于队列了
        std::cout << td->name << " 消费者拿到了一个数据:  " << t << std::endl;
        // t();
    }
}

int data = 1;

void *productor(void *args)
{
    threaddata *td = static_cast<threaddata*>(args);
    
    while (true)
    {
        sleep(1);
        // sleep(2);
        // 1. 获得任务
        // std::cout << "生产了一个任务: " << x << "+" << y << "=?" << std::endl;
        std::cout << td->name << " 生产了一个任务: " << data << std::endl;

        // 2. 生产任务
        td->rq->Equeue(data);

        data++;
    }
}

int main()
{
    // 扩展认识: 阻塞队列: 可以放任务吗？
    // 申请阻塞队列
    RingQueue<int> *rq = new RingQueue<int>();

    // 构建生产和消费者
    // 如果我们改成多生产多消费呢？？
    // 单单: cc, pp -> 互斥关系不需要维护，互斥与同步
    // 多多：cc, pp -> 之间的互斥关系！
    pthread_t c[2], p[3];

    threaddata *td = new threaddata();
    td->name = "cthread-1";
    td->rq = rq;
    pthread_create(c, nullptr, consumer, td);

    threaddata *td2 = new threaddata();
    td2->name = "cthread-2";
    td2->rq = rq;
    pthread_create(c + 1, nullptr, consumer, td2);

    threaddata *td3 = new threaddata();
    td3->name = "pthread-3";
    td3->rq = rq;
    pthread_create(p, nullptr, productor, td3);

    threaddata *td4 = new threaddata();
    td4->name = "pthread-4";
    td4->rq = rq;
    pthread_create(p + 1, nullptr, productor, td4);

    threaddata *td5 = new threaddata();
    td5->name = "pthread-5";
    td5->rq = rq;
    pthread_create(p + 2, nullptr, productor, td5);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);

    return 0;
}


// #include <iostream>
// #include <pthread.h>
// #include <unistd.h>
// #include"RingQueue.hpp"

// struct threaddata
// {
//     RingQueue<int>* rq;
//     std::string name;
// };

// void* consumer(void* argc)
// {
//     threaddata* td = static_cast<threaddata*> (argc);
//     int t = 0;
//     while(true)
//     {
//         sleep(3);
//         // 1. 消费任务
//         td->rq->Pop(&t);

//         // 2. 处理任务 -- 处理任务的时候，这个任务，已经被拿到线程的上下文中了,不属于队列了
//         std::cout << "消费者 name: " << td->name << ", 消费了一个内容" << t << std::endl; 
//         //t();
//     }
//     return nullptr;
// }
// int data = 1;
// void* productor(void* argc)
// {
//     threaddata* td = static_cast<threaddata*> (argc);
    
//     while(true)
//     {
//         sleep(1);
//         // 1. 获得任务
//         std::cout << "生产者 name: " << td->name << ", 生成了一个内容" << data << std::endl; 

//         // 2. 生产任务
//         td->rq->Equeue(data);
//         data++;  
//     }
//     return nullptr;
// }

// int main()
// {

//     pthread_t c[2], p[2];
//     RingQueue<int> *rq = new RingQueue<int>();

//     threaddata *tp1 = new threaddata();
//     tp1->name = "pthread-1";
//     tp1->rq = rq;
//     pthread_create(p, nullptr, productor, tp1);
 
//     threaddata *tp2 = new threaddata();
//     tp2->name = "pthread-2";
//     tp2->rq = rq;
//     pthread_create(p + 1, nullptr, productor, tp2);

//     threaddata *tc1 = new threaddata();
//     tc1->name = "cthread-1";
//     tc1->rq = rq;
//     pthread_create(c, nullptr, consumer, tc1);

//     threaddata *tc2 = new threaddata();
//     tc2->name = "cthread-1";
//     tc2->rq = rq;
//     pthread_create(c + 1, nullptr, consumer, tc2);

//     pthread_join(*c, nullptr);
//     pthread_join(*(c + 1), nullptr);
//     pthread_join(*p, nullptr);
//     pthread_join(*(p + 1), nullptr);


//     // pthread_t c, p;
//     // RingQueue<int> *rq = new RingQueue<int>();

//     // threaddata *tp = new threaddata();
//     // tp->name = "pthread-1";
//     // tp->rq = rq;
//     // pthread_create(&p, nullptr, productor, tp);
 
//     // threaddata *tc = new threaddata();
//     // tc->name = "cthread-1";
//     // tc->rq = rq;
//     // pthread_create(&c, nullptr, consumer, tc);



//     // pthread_join(c, nullptr);
//     // pthread_join(p, nullptr);

//     return 0;
// }